const content = document.getElementById("content").value;
const bytes = aesjs.utils.utf8.toBytes(content);
const k = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32];
const i = [21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36];
var ac = new aesjs.ModeOfOperation.cbc(k, i);
var eB = ac.encrypt(bytes);
var eH = aesjs.utils.hex.fromBytes(eB);
var eB = aesjs.utils.hex.toBytes(eH);
var ac = new aesjs.ModeOfOperation.cbc([...document.getElementById('flag').value].map(c => parseInt(c.charCodeAt(0))), i);
var dB = ac.decrypt(eB);
var dT = aesjs.utils.utf8.fromBytes(dB);
if(dT === document.getElementById("content").value) {
tldr, document.getElementById("content").value is some long text, the code first encrypts it using CBC (it is not exactly the same as aesjs lib, 1 minor change). Then it tries to take the flag input and decrypt, we need to get same result
The only change from aesjs:
in AES.prototype._prepare, normally it ends like screenshot show, but instead their code hard-coded the encryption round keys _Ke to something different in the end:
// inverse-cipher-ify the decryption round key (fips-197 section 5.3)
for (var r = 1; r < rounds; r++) {
for (var c = 0; c < 4; c++) {
tt = this._Kd[r][c];
this._Kd[r][c] = (U1[(tt >> 24) & 0xFF] ^
U2[(tt >> 16) & 0xFF] ^
U3[(tt >> 8) & 0xFF] ^
U4[ tt & 0xFF]);
}
}
this._Ke = [[1431127107, 1413905273, 880369457, 1601003876], [...]]; //HARDCODED